﻿namespace Behemoth.SharePoint.Branding {

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Text;
    using System.IO;
    using System.Linq;
    using System.Xml.Linq;

    using Behemoth.Configuration;
    using Behemoth.SharePoint.Logging;
    using Behemoth.SharePoint.Branding;

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Utilities;

    /// <summary>
    /// 
    /// </summary>
    /// <remarks>
    /// ReceiverAssembly="Behemoth.SharePoint.ARK, Version=1.?.?.?, Culture=neutral, PublicKeyToken=ecab56691def8148"
    /// ReceiverClass="Behemoth.SharePoint.Branding.BrandingFeatureReceiver"
    /// </remarks>
    public class BrandingFeatureReceiver : SPFeatureReceiver {

        #region Logging Code Pattern v2.0

        ////private ULSTraceLogging logWriter;

        protected string LOGGING_PRODUCT { get { return "Behemoth"; } }
        protected string LOGGING_CATEGORY { get { return "Branding"; } }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        public event LoggingEventHandler Logging;

        /// <summary>
        /// Put a method like this in your class that produces log entries
        /// </summary>
        /// <param name="e"></param>
        public void Log(LoggingEventArgs e) {
            // if nobody could be bothered to attach their own events, we should
            // still log things in the default way
            if (Logging == null)
                Logging += new LoggingEventHandler(ULSTraceLogging.Default.Log);
            if (Logging != null)
                Logging(this, e);
        }
        public void Log(string msg) {
            Log(msg, TraceSeverity.InformationEvent);
        }
        public void Log(string msg, TraceSeverity severity) {
            LoggingEventArgs e = new LoggingEventArgs(LOGGING_CATEGORY, LOGGING_PRODUCT, msg, severity);
            Log(e);
        }
        public void Log(Exception ex) {
            LoggingEventArgs e = new LoggingEventArgs(LOGGING_CATEGORY, LOGGING_PRODUCT, ex);
            Log(e);
        }

        #endregion

        private BrandingProperties brandProps;

        private void EnsureProperties(SPFeatureReceiverProperties properties) {
            Log("Invoking EnsureProperties.");
            if (brandProps == null)
                brandProps = new BrandingProperties(properties);
            else if (brandProps.InitStatus != Status.Initialized)
                throw new Exception("property reader is not initialized. Can't continue.");
            Log("Leaving EnsureProperties.");
        }

        public override void FeatureActivated(SPFeatureReceiverProperties properties) {
            EnsureProperties(properties);
            if (brandProps.Site == null)
                return;
            SPWeb web = brandProps.Web; //RootWeb
            MasterPageTools mpt = new MasterPageTools();
            mpt.Logging += Logging;
            if (brandProps.EnableResetMasterOnActivation) {
                Log("Invoking ProcessWeb for Activation.");
                try {
                    mpt.ProvisionMasterPages(brandProps, web, true, true);
                } catch (Exception ex) {
                    Log(ex);
                }
                Log("ProcessWeb for Activation Completed.");
            }
            try {
                ThemeTools.ModifySPTheme(
                    ThemeTools.ModificationType.Add,
                    brandProps.ThemeName,
                    brandProps.ThemeDisplayName,
                    brandProps.ThemeDescription,
                    brandProps.ThemePreviewImageName);
            } catch (Exception ex) {
                Log(string.Format("Exception while modifying system files for theme name '{0}'.", brandProps.ThemeName), TraceSeverity.Exception);
                Log(ex);
            }
            try {
                if (brandProps.ApplyTheme)
                    web.ApplyTheme(brandProps.ThemeName);
            } catch (Exception ex) {
                Log(string.Format("Exception while applying theme name '{0}'.", brandProps.ThemeName), TraceSeverity.Exception);
                Log(ex);
            }
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties) {
            EnsureProperties(properties);
            if (brandProps.Site == null)
                return;

            SPWeb web = brandProps.Web; // RootWeb
            MasterPageTools mpt = new MasterPageTools();
            mpt.Logging += Logging;
            if (brandProps.EnableDeleteGalleryFilesOnDeactivation) {
                try {
                    mpt.DeleteMasterPageFiles(brandProps);
                } catch (Exception ex) {
                    Log(ex);
                }
            }
            if (brandProps.EnableResetMasterOnDeactivation) {
                Log("Invoking ProcessWeb for Deactivation.");
                try {
                    mpt.ProvisionMasterPages(brandProps, web, true, true);
                } catch (Exception ex) {
                    Log(ex);
                }
                Log("ProcessWeb for Deactivation Completed.");
            }
            if (brandProps.ApplyTheme) {
                try {
                    web.ApplyTheme(ThemeTools.DEFAULT_THEME_NAME);
                } catch (Exception ex) {
                    Log(string.Format("Exception while applying theme name '{0}'.", ThemeTools.DEFAULT_THEME_NAME), TraceSeverity.Exception);
                    Log(ex);
                }
            }
        }

        public override void FeatureInstalled(SPFeatureReceiverProperties properties) {
            try {
                EnsureProperties(properties);
                ThemeTools.ModifySPTheme(
                    ThemeTools.ModificationType.Add, 
                    brandProps.ThemeName, 
                    brandProps.ThemeDisplayName,
                    brandProps.ThemeDescription, 
                    brandProps.ThemePreviewImageName);
            } catch (Exception ex) {
                Log(ex);
            }
        }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties) {
            EnsureProperties(properties);
            try {
                ThemeTools.ModifySPTheme(
                    ThemeTools.ModificationType.Remove, 
                    brandProps.ThemeName, 
                    brandProps.ThemeDisplayName,
                    brandProps.ThemeDescription, 
                    brandProps.ThemePreviewImageName);
            } catch (Exception ex) {
                Log(ex);
            }
        }

        /*
        #region Logging Code Pattern

        private void EnsureLogWriter()
        {
            if (logWriter != null)
                return;
            logWriter = new ULSTraceLogging();
            // also ensure that anything we put to the trace also gets logged to ULS
            //TODO: actually this does not seem to be working as intended, so we still log and trace seperately.
            SharepointTraceListener.EnsureListener(true, true);
        }
        private void WriteLog(string text)
        {
            EnsureLogWriter();
            logWriter.Write(text);
            Trace.WriteLine(text);
        }
        private void WriteLog(Exception ex)
        {
            EnsureLogWriter();
            logWriter.Write(ex);
            Trace.WriteLine(ex);
        }
        private void WriteLog(object textOrException)
        {
            Exception ex = textOrException as Exception;
            if (ex != null)
                WriteLog(ex);
            else
                WriteLog(textOrException.ToString());
        }

        #endregion
        */

    } // class
} // namespace

// TODO phase this out completely
namespace Behemoth.SharePoint.Receivers {

    using System;
    using Behemoth.SharePoint.Branding;

    [Obsolete("This class has been renamed to Behemoth.SharePoint.Branding.BrandingFeatureReceiver")]
    public class ChangeMasterFeatureReceiver : BrandingFeatureReceiver {

    } // class

} // namespace